#!/usr/bin/env node
/*
 * 模块脚手架生成脚本（ESM）
 * 用途：快速生成“列表/详情/表单/路由/Service/Mock”文件骨架
 * 使用示例：
 *   node scripts/generate-module.mjs --name html-code --entity HtmlCode
 * 参数说明：
 *   --name   必填，小写短横线命名，用作目录与路由前缀，例如 html-code
 *   --entity 必填，帕斯卡命名，用作类名和组件前缀，例如 HtmlCode
 */

import fs from 'fs';
import path from 'path';
import url from 'url';

// 解析当前工作目录
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
const root = path.resolve(__dirname, '..');

// 解析命令行参数
const args = process.argv.slice(2);
const getArg = (key) => {
  const idx = args.indexOf(`--${key}`);
  return idx !== -1 ? args[idx + 1] : undefined;
};

const moduleName = getArg('name'); // 例如 html-code
const entityName = getArg('entity'); // 例如 HtmlCode

if (!moduleName || !entityName) {
  console.error('[错误] 缺少必填参数：--name 与 --entity');
  console.error('示例：node scripts/generate-module.mjs --name post --entity Post');
  process.exit(1);
}

// 驼峰/帕斯卡命名辅助
const toCamel = (s) => s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
const toPascal = (s) => toCamel(s).replace(/^./, (c) => c.toUpperCase());

const camel = toCamel(moduleName); // htmlCode
const pascal = entityName; // HtmlCode

// 目标路径
const pagesDir = path.join(root, 'src', 'pages', `${moduleName}-management`);
const servicesDir = path.join(root, 'src', 'lib', 'api', 'services');
const mockDir = path.join(root, 'src', 'lib', 'api', 'mock-data');

// 确保目录存在
const ensureDir = (p) => fs.mkdirSync(p, { recursive: true });
ensureDir(pagesDir);
ensureDir(servicesDir);
ensureDir(mockDir);

// 工具：写文件（若存在则跳过，可传入 --force 覆盖）
const force = args.includes('--force');
const writeFile = (absPath, content) => {
  if (fs.existsSync(absPath) && !force) {
    console.log(`[跳过] 已存在：${path.relative(root, absPath)}`);
    return;
  }
  fs.writeFileSync(absPath, content, 'utf8');
  console.log(`[创建] ${path.relative(root, absPath)}`);
};

// ========== 模板内容 ==========

// 列表页模板（最小可运行骨架，使用项目封装 UI）
const listPage = `import React from 'react';
import { Link } from 'react-router-dom';
import { Container } from '@/components/ui/container';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { ResponsiveTable, ResponsiveTableHeader, ResponsiveTableBody, ResponsiveTableRow, ResponsiveTableCell } from '@/components/ui/responsive-table';
import { useQuery } from '@tanstack/react-query';
import ${camel}Service from '@/lib/api/services/${moduleName}-service';

// 列表页：展示基础字段，保留搜索/筛选与分页扩展位
const ${pascal}ListPage = () => {
  const service = React.useMemo(() => new ${camel}Service(), []);
  const { data, isLoading, error, refetch } = useQuery({
    queryKey: ['${moduleName}', 'list'],
    queryFn: () => service.list({ page: 1, pageSize: 10 })
  });

  const rows = data?.data || [];

  return (
    <Container>
      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle>${pascal} 列表</CardTitle>
            <Link to="/` + `${moduleName}-management` + `/create"><Button>新建</Button></Link>
          </div>
        </CardHeader>
        <CardContent>
          <ResponsiveTable>
            <ResponsiveTableHeader columns={["ID", "名称", "操作"]} />
            <ResponsiveTableBody>
              {isLoading ? (
                <ResponsiveTableRow>
                  <ResponsiveTableCell colSpan={3}>加载中...</ResponsiveTableCell>
                </ResponsiveTableRow>
              ) : error ? (
                <ResponsiveTableRow>
                  <ResponsiveTableCell colSpan={3}>加载失败 <Button variant="outline" onClick={refetch}>重试</Button></ResponsiveTableCell>
                </ResponsiveTableRow>
              ) : rows.length === 0 ? (
                <ResponsiveTableRow>
                  <ResponsiveTableCell colSpan={3}>暂无数据</ResponsiveTableCell>
                </ResponsiveTableRow>
              ) : (
                rows.map((item) => (
                  <ResponsiveTableRow key={item.id}>
                    <ResponsiveTableCell>{item.id}</ResponsiveTableCell>
                    <ResponsiveTableCell>{item.name}</ResponsiveTableCell>
                    <ResponsiveTableCell>
                      <Link to={"/` + `${moduleName}-management` + `/edit/" + item.id} className="text-primary">详情</Link>
                    </ResponsiveTableCell>
                  </ResponsiveTableRow>
                ))
              )}
            </ResponsiveTableBody>
          </ResponsiveTable>
        </CardContent>
      </Card>
    </Container>
  );
};

export default ${pascal}ListPage;`;

// 表单页模板
const formPage = `import React from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { Container } from '@/components/ui/container';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import ${camel}Service from '@/lib/api/services/${moduleName}-service';

const ${pascal}FormPage = () => {
  const { id } = useParams();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const service = React.useMemo(() => new ${camel}Service(), []);

  const { data } = useQuery({
    queryKey: ['${moduleName}', 'detail', id],
    queryFn: () => service.detail(id),
    enabled: !!id
  });

  const [form, setForm] = React.useState({ name: '' });
  React.useEffect(() => { if (data?.data) setForm({ name: data.data.name || '' }); }, [data]);

  const saveMutation = useMutation({
    mutationFn: (payload) => id ? service.update(id, payload) : service.create(payload),
    onSuccess: () => {
      queryClient.invalidateQueries(['${moduleName}']);
      navigate('/` + `${moduleName}-management` + `');
    }
  });

  const handleChange = (k, v) => setForm((s) => ({ ...s, [k]: v }));

  return (
    <Container>
      <Tabs defaultValue="form">
        <TabsList>
          <TabsTrigger value="form">基本信息</TabsTrigger>
        </TabsList>
        <TabsContent value="form">
          <Card>
            <CardHeader><CardTitle>{id ? '编辑' : '新建'} ${pascal}</CardTitle></CardHeader>
            <CardContent className="space-y-4">
              <div className="space-y-2">
                <Label>名称</Label>
                <Input value={form.name} onChange={(e) => handleChange('name', e.target.value)} placeholder="请输入名称" />
              </div>
              <div className="flex items-center justify-end gap-2 pt-4 border-t">
                <Button variant="outline" onClick={() => navigate(-1)}>取消</Button>
                <Button onClick={() => saveMutation.mutate(form)} disabled={saveMutation.isPending}>保存</Button>
              </div>
            </CardContent>
          </Card>
        </TabsContent>
      </Tabs>
    </Container>
  );
};

export default ${pascal}FormPage;`;

// 详情页模板（可与表单复用，这里给独立示例）
const detailPage = `import React from 'react';
import { useParams } from 'react-router-dom';
import { Container } from '@/components/ui/container';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { useQuery } from '@tanstack/react-query';
import ${camel}Service from '@/lib/api/services/${moduleName}-service';

const ${pascal}DetailPage = () => {
  const { id } = useParams();
  const service = React.useMemo(() => new ${camel}Service(), []);
  const { data } = useQuery({ queryKey: ['${moduleName}', 'detail', id], queryFn: () => service.detail(id), enabled: !!id });
  const item = data?.data;

  return (
    <Container>
      <Card>
        <CardHeader><CardTitle>${pascal} 详情</CardTitle></CardHeader>
        <CardContent>
          {!item ? '加载中...' : (
            <div className="space-y-2">
              <div><b>ID：</b>{item.id}</div>
              <div><b>名称：</b>{item.name}</div>
            </div>
          )}
        </CardContent>
      </Card>
    </Container>
  );
};

export default ${pascal}DetailPage;`;

// 路由聚合文件模板
const routing = `import React from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import ${pascal}ListPage from './${moduleName}-list-page';
import ${pascal}FormPage from './${moduleName}-form-page';
import ${pascal}DetailPage from './${moduleName}-detail-page';

const ${pascal}Routing = () => (
  <Routes>
    <Route index element={<${pascal}ListPage />} />
    <Route path="create" element={<${pascal}FormPage />} />
    <Route path="edit/:id" element={<${pascal}FormPage />} />
    <Route path="detail/:id" element={<${pascal}DetailPage />} />
    <Route path="*" element={<Navigate to="." replace />} />
  </Routes>
);

export default ${pascal}Routing;`;

// Service 模板（支持 Mock 切换）
const service = `import BaseService from '../base-service';
import { API_CONFIG } from '../config';
import * as mock from '../mock-data/${moduleName}-mock-data';

export default class ${pascal}Service extends BaseService {
  constructor() { super('/${moduleName}s'); }

  list(params) {
    if (API_CONFIG?.${pascal?.toUpperCase?.() || pascal}?.USE_MOCK_DATA) return mock.list(params);
    return this.get('/', { params });
  }
  detail(id) {
    if (API_CONFIG?.${pascal?.toUpperCase?.() || pascal}?.USE_MOCK_DATA) return mock.detail(id);
    return this.get('/' + id);
  }
  create(payload) {
    if (API_CONFIG?.${pascal?.toUpperCase?.() || pascal}?.USE_MOCK_DATA) return mock.create(payload);
    return this.post('/', payload);
  }
  update(id, payload) {
    if (API_CONFIG?.${pascal?.toUpperCase?.() || pascal}?.USE_MOCK_DATA) return mock.update(id, payload);
    return this.put('/' + id, payload);
  }
  remove(id) {
    if (API_CONFIG?.${pascal?.toUpperCase?.() || pascal}?.USE_MOCK_DATA) return mock.remove(id);
    return this.delete('/' + id);
  }
}
`;

// Mock 数据模板
const mockData = `// 简易内存 Mock，生产环境请移除
let DB = [
  { id: 1, name: '${pascal} 示例 1' },
  { id: 2, name: '${pascal} 示例 2' }
];

const delay = (ms = 300) => new Promise(r => setTimeout(r, ms));

export async function list(params) {
  await delay();
  return { data: DB, meta: { page: 1, pageSize: DB.length, total: DB.length } };
}
export async function detail(id) { await delay(); return { data: DB.find(i => i.id == id) }; }
export async function create(payload) { await delay(); const id = DB.length ? Math.max(...DB.map(i => i.id)) + 1 : 1; const item = { id, ...payload }; DB.push(item); return { data: item }; }
export async function update(id, payload) { await delay(); DB = DB.map(i => i.id == id ? { ...i, ...payload } : i); return { data: DB.find(i => i.id == id) }; }
export async function remove(id) { await delay(); DB = DB.filter(i => i.id != id); return { data: true }; }
`;

// 写入文件
writeFile(path.join(pagesDir, `${moduleName}-list-page.jsx`), listPage);
writeFile(path.join(pagesDir, `${moduleName}-form-page.jsx`), formPage);
writeFile(path.join(pagesDir, `${moduleName}-detail-page.jsx`), detailPage);
writeFile(path.join(pagesDir, `${moduleName}-routing.jsx`), routing);
writeFile(path.join(servicesDir, `${moduleName}-service.js`), service);
writeFile(path.join(mockDir, `${moduleName}-mock-data.js`), mockData);

// 友好提示
console.log('\n[完成] 基本文件已生成。下一步：');
console.log('1) 在 src/routing/app-routing-setup.jsx 中挂载路由：');
console.log(`   <Route path="/${moduleName}-management/*" element={<${pascal}Routing />} />`);
console.log('2) 在 src/config/menu.config.jsx 中添加菜单入口。');
console.log('3) 如需使用 Mock，请在 API_CONFIG 中开启对应模块的 USE_MOCK_DATA。');


